using System.Diagnostics;
using System.Runtime;
using Microsoft.Data.SqlClient;
using Oracle.ManagedDataAccess.Client;
using Microsoft.Extensions.Options;
using Lzfy_His_Service.Models;
using Lzfy_His_Service.Repositories;

namespace Lzfy_His_Service.Services
{
    /// <summary>
    /// 应用程序健康检查服务
    /// </summary>
    public class ApplicationHealthCheckService : BackgroundService
    {
        private readonly ILogger<ApplicationHealthCheckService> _logger;
        private readonly IServiceProvider _serviceProvider;
        private readonly IDatabaseConfigurationService _dbConfigService;
        private readonly IOracleConnectionFactory _oracleConnectionFactory;
        private readonly FileStorageOptions _fileStorageOptions;
        private readonly TimeSpan _checkInterval = TimeSpan.FromMinutes(1); // 每分钟检查一次
        
        // 健康状态
        private bool _isHealthy = true;
        private DateTime _lastHealthCheckTime = DateTime.MinValue;
        private readonly Dictionary<string, object> _healthMetrics = new();
        private readonly object _metricsLock = new object();

        public ApplicationHealthCheckService(
            ILogger<ApplicationHealthCheckService> logger,
            IServiceProvider serviceProvider,
            IDatabaseConfigurationService dbConfigService,
            IOracleConnectionFactory oracleConnectionFactory,
            IOptions<FileStorageOptions> fileStorageOptions)
        {
            _logger = logger;
            _serviceProvider = serviceProvider;
            _dbConfigService = dbConfigService;
            _oracleConnectionFactory = oracleConnectionFactory;
            _fileStorageOptions = fileStorageOptions.Value;
        }

        protected override async Task ExecuteAsync(CancellationToken stoppingToken)
        {
            _logger.LogInformation("应用健康检查服务启动");

            while (!stoppingToken.IsCancellationRequested)
            {
                try
                {
                    await PerformHealthCheckAsync();
                }
                catch (Exception ex)
                {
                    _logger.LogError(ex, "执行应用健康检查时发生异常");
                }

                try
                {
                    await Task.Delay(_checkInterval, stoppingToken);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
            }

            _logger.LogInformation("应用健康检查服务停止");
        }

        /// <summary>
        /// 执行健康检查
        /// </summary>
        private async Task PerformHealthCheckAsync()
        {
            var healthStatus = new Dictionary<string, object>();
            bool overallHealth = true;

            try
            {
                // 1. 检查内存使用情况
                var memoryInfo = CheckMemoryUsage();
                healthStatus["memory"] = memoryInfo;
                if ((long)memoryInfo["usedMemoryMB"] > 1024) // 超过1GB警告
                {
                    _logger.LogWarning("内存使用量较高: {UsedMemory}MB", memoryInfo["usedMemoryMB"]);
                }

                // 2. 检查数据库连接
                var dbHealth = await CheckDatabaseHealthAsync();
                healthStatus["database"] = dbHealth;
                if (!(bool)dbHealth["sqlServerHealthy"] || !(bool)dbHealth["oracleHealthy"])
                {
                    overallHealth = false;
                    _logger.LogWarning("数据库连接异常");
                }

                // 3. 检查文件系统
                var fileSystemHealth = CheckFileSystemHealth();
                healthStatus["fileSystem"] = fileSystemHealth;
                if (!(bool)fileSystemHealth["isHealthy"])
                {
                    overallHealth = false;
                    _logger.LogWarning("文件系统异常");
                }

                // 4. 检查线程池状态
                var threadPoolInfo = CheckThreadPoolStatus();
                healthStatus["threadPool"] = threadPoolInfo;

                // 5. 检查GC状态
                var gcInfo = CheckGCStatus();
                healthStatus["gc"] = gcInfo;

                // 更新健康状态
                lock (_metricsLock)
                {
                    _isHealthy = overallHealth;
                    _lastHealthCheckTime = DateTime.Now;
                    _healthMetrics.Clear();
                    foreach (var kvp in healthStatus)
                    {
                        _healthMetrics[kvp.Key] = kvp.Value;
                    }
                }

                if (!overallHealth)
                {
                    _logger.LogWarning("应用健康检查发现问题，尝试自动恢复");
                    await AttemptAutoRecoveryAsync();
                }
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "健康检查执行失败");
                lock (_metricsLock)
                {
                    _isHealthy = false;
                }
            }
        }

        /// <summary>
        /// 检查内存使用情况
        /// </summary>
        private Dictionary<string, object> CheckMemoryUsage()
        {
            var process = Process.GetCurrentProcess();
            var gcInfo = GC.GetTotalMemory(false);
            
            return new Dictionary<string, object>
            {
                ["workingSetMB"] = process.WorkingSet64 / 1024 / 1024,
                ["usedMemoryMB"] = gcInfo / 1024 / 1024,
                ["gen0Collections"] = GC.CollectionCount(0),
                ["gen1Collections"] = GC.CollectionCount(1),
                ["gen2Collections"] = GC.CollectionCount(2)
            };
        }

        /// <summary>
        /// 检查数据库健康状态
        /// </summary>
        private async Task<Dictionary<string, object>> CheckDatabaseHealthAsync()
        {
            bool sqlServerHealthy = false;
            bool oracleHealthy = false;

            try
            {
                // 检查SQL Server
                using var sqlConn = new SqlConnection(_dbConfigService.GetDefaultConnection());
                await sqlConn.OpenAsync();
                using var sqlCmd = sqlConn.CreateCommand();
                sqlCmd.CommandText = "SELECT 1";
                sqlCmd.CommandTimeout = 5;
                await sqlCmd.ExecuteScalarAsync();
                sqlServerHealthy = true;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "SQL Server连接检查失败");
            }

            try
            {
                // 检查Oracle - 使用连接工厂
                using var oracleConn = (OracleConnection)_oracleConnectionFactory.CreateConnection();
                await oracleConn.OpenAsync();
                using var oracleCmd = oracleConn.CreateCommand();
                oracleCmd.CommandText = "SELECT 1 FROM DUAL";
                oracleCmd.CommandTimeout = 5;
                await oracleCmd.ExecuteScalarAsync();
                oracleHealthy = true;
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "Oracle连接检查失败");
            }

            return new Dictionary<string, object>
            {
                ["sqlServerHealthy"] = sqlServerHealthy,
                ["oracleHealthy"] = oracleHealthy,
                ["checkTime"] = DateTime.Now
            };
        }

        /// <summary>
        /// 检查文件系统健康状态
        /// </summary>
        private Dictionary<string, object> CheckFileSystemHealth()
        {
            try
            {
                var testPath = Path.Combine(_fileStorageOptions.RootPath, "health-check-test.txt");
                var testContent = $"Health check at {DateTime.Now:yyyy-MM-dd HH:mm:ss}";
                
                File.WriteAllText(testPath, testContent);
                var readContent = File.ReadAllText(testPath);
                File.Delete(testPath);
                
                return new Dictionary<string, object>
                {
                    ["isHealthy"] = readContent == testContent,
                    ["testPath"] = testPath
                };
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "文件系统健康检查失败");
                return new Dictionary<string, object>
                {
                    ["isHealthy"] = false,
                    ["error"] = ex.Message
                };
            }
        }

        /// <summary>
        /// 检查线程池状态
        /// </summary>
        private Dictionary<string, object> CheckThreadPoolStatus()
        {
            ThreadPool.GetMinThreads(out int workerThreads, out int ioThreads);
            ThreadPool.GetMaxThreads(out int maxWorkerThreads, out int maxIoThreads);
            ThreadPool.GetAvailableThreads(out int availableWorkerThreads, out int availableIoThreads);
            
            return new Dictionary<string, object>
            {
                ["minWorkerThreads"] = workerThreads,
                ["minIoThreads"] = ioThreads,
                ["maxWorkerThreads"] = maxWorkerThreads,
                ["maxIoThreads"] = maxIoThreads,
                ["availableWorkerThreads"] = availableWorkerThreads,
                ["availableIoThreads"] = availableIoThreads,
                ["busyWorkerThreads"] = maxWorkerThreads - availableWorkerThreads,
                ["busyIoThreads"] = maxIoThreads - availableIoThreads
            };
        }

        /// <summary>
        /// 检查GC状态
        /// </summary>
        private Dictionary<string, object> CheckGCStatus()
        {
            var gen0 = GC.CollectionCount(0);
            var gen1 = GC.CollectionCount(1);
            var gen2 = GC.CollectionCount(2);
            var totalMemory = GC.GetTotalMemory(false);
            
            return new Dictionary<string, object>
            {
                ["gen0Collections"] = gen0,
                ["gen1Collections"] = gen1,
                ["gen2Collections"] = gen2,
                ["totalMemoryMB"] = totalMemory / 1024 / 1024,
                ["latencyMode"] = GCSettings.LatencyMode.ToString()
            };
        }

        /// <summary>
        /// 尝试自动恢复
        /// </summary>
        private async Task AttemptAutoRecoveryAsync()
        {
            try
            {
                // 强制垃圾回收 - 使用 Task.Run 包装同步操作
                await Task.Run(() => 
                {
                    GC.Collect();
                    GC.WaitForPendingFinalizers();
                });
                
                _logger.LogInformation("已执行垃圾回收");
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "自动恢复失败");
            }
        }

        /// <summary>
        /// 获取当前健康状态
        /// </summary>
        public (bool isHealthy, DateTime lastCheckTime, Dictionary<string, object> metrics) GetHealthStatus()
        {
            lock (_metricsLock)
            {
                return (_isHealthy, _lastHealthCheckTime, new Dictionary<string, object>(_healthMetrics));
            }
        }
    }
}